package com.lbd.gulimall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.lbd.common.constrant.ProductConstrant;
import com.lbd.gulimall.product.entity.AttrAttrgroupRelationEntity;
import com.lbd.gulimall.product.entity.AttrGroupEntity;
import com.lbd.gulimall.product.entity.CategoryEntity;
import com.lbd.gulimall.product.service.AttrAttrgroupRelationService;
import com.lbd.gulimall.product.service.AttrGroupService;
import com.lbd.gulimall.product.service.CategoryService;
import com.lbd.gulimall.product.vo.AttrResponseVO;
import com.lbd.gulimall.product.vo.AttrVO;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lbd.common.utils.PageUtils;
import com.lbd.common.utils.Query;

import com.lbd.gulimall.product.dao.AttrDao;
import com.lbd.gulimall.product.entity.AttrEntity;
import com.lbd.gulimall.product.service.AttrService;
import org.springframework.util.StringUtils;


@Service("attrService")
public class AttrServiceImpl extends ServiceImpl<AttrDao, AttrEntity> implements AttrService {
    @Autowired
    private AttrAttrgroupRelationService attrAttrgroupRelationService;
    @Autowired
    private AttrGroupService attrGroupService;
    @Autowired
    private CategoryService categoryService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                new QueryWrapper<AttrEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public void saveAttr(AttrVO attrVO) {
        AttrEntity attr = new AttrEntity();
        //(源数据，目标数据)
        BeanUtils.copyProperties(attrVO,attr);
        this.save(attr);
        //需要关联属性组和属性
        Long attrGroupId = attrVO.getAttrGroupId();
        //主要不要使用attrVO来获取，因为新增的时候表单不提交ID所以会拿到null,应该去新增后的attr记录去拿
        //Long attrId = attrVO.getAttrId();
        //如果组ID为空，则关联表不插入组ID为空的记录
        if (attrVO.getAttrType() == ProductConstrant.AttrType.BASE.getCode() && attrGroupId != null) {
            AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = new AttrAttrgroupRelationEntity();
            attrAttrgroupRelationEntity.setAttrGroupId(attrGroupId);
            //新增后，attr会自动同步新增的值（id）到对象的属性中
            attrAttrgroupRelationEntity.setAttrId(attr.getAttrId());
            attrAttrgroupRelationService.save(attrAttrgroupRelationEntity);
        }
    }

    @Override
    public PageUtils queryAttrList(Map<String, Object> params, Long catelogId, String type) {
        QueryWrapper<AttrEntity> wrapper = new QueryWrapper<AttrEntity>()
                .eq("attr_type",type.equalsIgnoreCase("base")
                        ? ProductConstrant.AttrType.BASE.getCode()
                        : ProductConstrant.AttrType.SALE.getCode());
        if (catelogId != 0) {
            wrapper.eq("catelog_id",catelogId);
        }
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            wrapper.and(condition -> {
                condition.eq("attr_id",key).or().like("attr_name",key);
            });
        }
        IPage<AttrEntity> page = this.page(
                new Query<AttrEntity>().getPage(params),
                wrapper
        );
        PageUtils pageUtils = new PageUtils(page);
        List<AttrEntity> records = page.getRecords();
        List<AttrResponseVO> attrResponseVOS = records.stream()
                .map(attrEntity -> {
                    AttrResponseVO attrResponseVO = new AttrResponseVO();
                    BeanUtils.copyProperties(attrEntity,attrResponseVO);
                    Long attrId = attrEntity.getAttrId();
                    //基本信息才有分组项
                    if (attrEntity.getAttrType() == ProductConstrant.AttrType.BASE.getCode() ) {
                        AttrAttrgroupRelationEntity entity = attrAttrgroupRelationService
                                .getOne(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));
                        if (entity != null) {
                            Long attrGroupId = entity.getAttrGroupId();
                            AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrGroupId);
                            if (attrGroupEntity != null) {
                                attrResponseVO.setGroupName(attrGroupEntity.getAttrGroupName());
                            }
                        }
                    }
                    //分类信息
                    Long catelogId1 = attrEntity.getCatelogId();
                    CategoryEntity categoryEntity = categoryService.getById(catelogId1);
                    if (categoryEntity != null) {
                        attrResponseVO.setCatelogName(categoryEntity.getName());
                    }
                    return attrResponseVO;
                })
                .collect(Collectors.toList());
        pageUtils.setList(attrResponseVOS);
        return pageUtils;
    }

    //缓存方法，缓存分区为attr，key为attrInfo_attrId   这个方法有作用于面包屑检索，经常被大量用户用于检索，使用频率高，需要防止缓存击穿
    @Cacheable(value = "attr",key = "'attrInfo' + #root.args[0]",sync = true)
    @Override
    public AttrResponseVO getAttrInfo(Long attrId) {
        AttrEntity attrEntity = this.getById(attrId);
        AttrResponseVO attrResponseVO = new AttrResponseVO();
        if (attrEntity != null) {
            BeanUtils.copyProperties(attrEntity,attrResponseVO);
            Long[] catelogPath = categoryService.getCatelogPath(attrEntity.getCatelogId());
            attrResponseVO.setCatelogPath(catelogPath);
            CategoryEntity categoryEntity = categoryService
                    .getOne(new QueryWrapper<CategoryEntity>().eq("cat_id", attrEntity.getCatelogId()));
            if (categoryEntity != null) {
                attrResponseVO.setCatelogName(categoryEntity.getName());
            }

            if (attrEntity.getAttrType() == ProductConstrant.AttrType.BASE.getCode()) {
                AttrAttrgroupRelationEntity attrAttrgroupRelationEntity = attrAttrgroupRelationService
                        .getOne(new QueryWrapper<AttrAttrgroupRelationEntity>()
                                .eq("attr_id", attrEntity.getAttrId()));
                if (attrAttrgroupRelationEntity != null) {
                    attrResponseVO.setAttrGroupId(attrAttrgroupRelationEntity.getAttrGroupId());
                    AttrGroupEntity attrGroupEntity = attrGroupService
                            .getById(attrAttrgroupRelationEntity.getAttrGroupId());
                    if (attrGroupEntity != null) {
                        attrResponseVO.setGroupName(attrGroupEntity.getAttrGroupName());
                    }
                }
            }
        }
        return attrResponseVO;
    }

    @Override
    public void updateAttr(AttrVO attrVO) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVO,attrEntity);
        this.updateById(attrEntity);

        Long attrId = attrVO.getAttrId();
        AttrAttrgroupRelationEntity entity = new AttrAttrgroupRelationEntity();

        if (attrVO.getAttrType() == ProductConstrant.AttrType.BASE.getCode()) {
            Long attrGroupId = attrVO.getAttrGroupId();
            entity.setAttrGroupId(attrGroupId);
        }

        entity.setAttrId(attrId);
        //有可能在添加新的属性时，没有绑定分组，于是在修改的时候，关联表没有数据导致无法修改
        //因此可以根据属性ID去关联表查出有没有这条记录，有就代表有绑定过，就做修改，否则新增一条不带组id的关联表数据，以便后续修改请求有记录可操作
        int count = attrAttrgroupRelationService
                .count(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_id", attrId));
        if (count > 0) {
            //修改
            attrAttrgroupRelationService
                    .update(entity,new UpdateWrapper<AttrAttrgroupRelationEntity>().eq("attr_id",attrId));
        }else {
            //新增
            attrAttrgroupRelationService.save(entity);
        }
    }

    /**
     * 查询分组下关联的属性
     *
     * @return:
     * @author: linbd
     * @date: 2021/6/17 20:16
     */
    @Override
    public List<AttrEntity> getRelation(Long attrgroupId) {
        List<AttrAttrgroupRelationEntity> attrAttrgroupRelationEntities = attrAttrgroupRelationService
                .list(new QueryWrapper<AttrAttrgroupRelationEntity>().eq("attr_group_id", attrgroupId));
        List<Long> attrIds = attrAttrgroupRelationEntities
                .stream().map(item -> item.getAttrId()).collect(Collectors.toList());
        List<AttrEntity> attrEntities = new ArrayList<>();
        if (attrIds != null && attrIds.size() > 0) {
            attrEntities = this.listByIds(attrIds);
        }
        return attrEntities;
    }

    @Override
    public PageUtils getNoAttrRelation(Long attrgroupId, Map<String, Object> params) {
        IPage<AttrEntity> page = null;
        AttrGroupEntity attrGroupEntity = attrGroupService.getById(attrgroupId);
        if (attrGroupEntity != null) {
            //根据组ID查出组所属的分类ID
            Long catelogId = attrGroupEntity.getCatelogId();
            //通过分类ID检索出该分类下所有的组，包括本身（因为检索未关联组的属性时，也要加入自身，否则无法排除改组下的属性）
            List<AttrGroupEntity> attrGroups = attrGroupService
                    .list(new QueryWrapper<AttrGroupEntity>()
                            .eq("catelog_id", catelogId));
            if (attrGroups != null) {
                //查出这些组中已经和属性关联的属性Id
                List<Long> attrGroupIds = attrGroups.stream().map(item -> item.getAttrGroupId()).collect(Collectors.toList());
                List<AttrAttrgroupRelationEntity> attrAttrgroupRelations = attrAttrgroupRelationService
                        .list(new QueryWrapper<AttrAttrgroupRelationEntity>().in("attr_group_id",attrGroupIds));
                if (attrAttrgroupRelations != null) {
                    List<Long> attrIds = attrAttrgroupRelations.stream().map(item -> item.getAttrId()).collect(Collectors.toList());
                    //查询未被分组关联的属性
                    QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>()
                            .eq("attr_type", ProductConstrant.AttrType.BASE.getCode())
                            .eq("catelog_id", catelogId);
                    if (attrIds != null && attrIds.size() > 0) {
                        queryWrapper.notIn("attr_id", attrIds);
                    }
                    //检索信息
                    String key = (String) params.get("key");
                    if (key != null) {
                        queryWrapper.and(item -> {
                            item.eq("attr_id",key).or().like("attr_name",key);
                        });
                    }
                    //最终需要返回分页对象，所以把属性信息封装到分页对象
                    page = this.page(
                            new Query<AttrEntity>().getPage(params),
                            queryWrapper
                    );
                }
            }
        }
        return new PageUtils(page);
    }

    @Override
    public List<Long> selectByIds(List<Long> attrIds, int searchType) {
        return baseMapper.selectByIds(attrIds,searchType);
    }

}